#!/usr/bin/env python3
# coding=utf-8

'''
转换音乐文件以便传到手机

参数为源目录和目的目录，从 stdin 读取文件列表（相对于源目录）

目前主要用于 musicselect.vim 插件和 musicmodified 程序
'''

import sys, os
import queue
import threading
from lilypath import path
import subprocess
import stagger

THREAD_NUM = 2
LOGFILE = path('~/etc/log/musicconvert').expand()
tmpprefix = str(path('~/tmpfs/inprogress').expand())

q = queue.Queue()
err = []
tagwritelock = threading.Condition()
tagwritedata = [None, None, None]

def worker():
  while True:
    item = q.get()
    song = os.path.join(srcdir, item)
    tmpsong = tmpprefix + '.%d' % threading.current_thread().ident
    try:
      tag = stagger.read_tag(song)
    except stagger.errors.NoTagError:
      tag = stagger.tags.Tag24()
      tag.artist, tag.title = os.path.splitext(item)[0].split('/')
      tag.album = '未知'
    dstsong = os.path.join(dstdir, item)
    try:
      path(dstsong).parent().mkdir()
    except OSError: # File exists
      pass
    cmd = ['lame', '--quiet', '-q', '2', '--cbr', '-b', '96', '--noreplaygain',
      song, tmpsong]
    status = subprocess.call(cmd)
    if status:
      err.append(item)
    else:
      # stagger 用到了信号，但信号只能在主线程中设置
      waiting = threading.Condition()
      tagwritelock.acquire()
      tagwritedata[0] = tag
      tagwritedata[1] = tmpsong
      tagwritedata[2] = waiting
      tagwritelock.notify()
      tagwritelock.release()
      waiting.acquire()
      waiting.wait()
      path(tmpsong).moveto(dstsong)
      waiting.release()
    q.task_done()

def main():
  global srcdir, dstdir
  try:
    _, srcdir, dstdir = sys.argv
  except ValueError:
    print('参数错误', file=sys.stderr)
    sys.exit(-1)

  for i in range(THREAD_NUM):
     t = threading.Thread(target=worker)
     t.daemon = True
     t.start()

  itemcount = 0
  for i in sys.stdin:
    itemcount += 1
    q.put(i.strip())

  while itemcount != 0:
    tagwritelock.acquire()
    tagwritelock.wait()
    if tagwritedata[0] is not None:
      tagwritedata[0].write(tagwritedata[1])
    tagwritelock.release()
    tagwritedata[2].acquire()
    tagwritedata[2].notify()
    tagwritedata[2].release()
    itemcount -= 1
  q.join()

  if err:
    with LOGFILE.open('w') as log:
      for i in err:
        print(i, file=log)
    sys.exit(len(err))

if __name__ == '__main__':
  main()
